package com.cskt.petproject178.service.third;

import com.cskt.petproject178.config.WeChatLoginAutoConfigProperties;
import com.cskt.petproject178.mapper.UserMapper;
import com.cskt.petproject178.pojo.entity.User;
import com.cskt.petproject178.pojo.exception.BaseException;
import com.cskt.petproject178.pojo.vo.ResultStatusEnum;
import com.cskt.petproject178.pojo.vo.StatusEnum;
import com.cskt.petproject178.pojo.vo.UserInfoVO;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author 27013
 **/

@Service
public class WeChatLoginService {
    private static  final Logger log= LoggerFactory.getLogger(WeChatLoginService.class);
    @Resource
    private WeChatLoginAutoConfigProperties properties;
    @Resource
    private RestTemplate restTemplate;//发送http请求的工具类,使用前必须先声明
    @Resource
    private ObjectMapper objectMapper;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private UserMapper userMapper;
    /**
     * 微信登录回调，根据微信服务器返回的code获取微信用户信息， 将其存入到redis，并返回token
     * @return
     */
    public String weChatLoginBack(String code){
        //1、先根据code获取access_token
       String accessTokenUrl="https://api.weixin.qq.com/sns/oauth2/access_token?appid="+properties.getAppId()+"&secret="+properties.getAppSecret()+"&code="+code+"&grant_type=authorization_code";
       //发起请求获取access_token
        String accessTokenResult = restTemplate.getForObject(accessTokenUrl, String.class);
        if (accessTokenResult.contains("errcode")) {
            //表示获取accessToken接口请求异常
            log.warn("微信登录回调根据code获取access_token出行异常，{}，{}",code,accessTokenResult);
            throw  new BaseException(StatusEnum.COMMON_EXCEPTION);
        }
        //从响应结果中取出access_token，先将string类型转化为JsonNode
        try {
            //先借助于typeReference把Json格式的字符串转换成为Map
            Map<String,String> accessTokenMap = objectMapper.readValue(accessTokenResult, new TypeReference<>() {
            });
            //从Map中取出access_token
            String accessToken = accessTokenMap.get("access_token");
            //从Map中取出openid
            String openId = accessTokenMap.get("openid");
           /* JsonNode accessTokenJsonNode = objectMapper.readTree(accessTokenResult);
            String accessToken = accessTokenJsonNode.get("access_token").asText();*/
            //2、根据access_token获取用户信息
            String userInfoUrl="https://api.weixin.qq.com/sns/userinfo?access_token="+accessToken+"&openid="+openId;
            //发起请求
            String userInfoStr = restTemplate.getForObject(userInfoUrl, String.class);
            //判断响应结果是否异常
            if (userInfoUrl.contains("errcode")) {
                log.warn("微信登录回调根据access_token获取用户信息异常,{}",userInfoUrl);
            }
            //类型转换
            Map<String,Object> userInfoMap = objectMapper.readValue(userInfoStr, new TypeReference<>() {
            });

            //3、验证用户信息是否存在，如果不存在，则将其存入数据库
            User user = userMapper.selectByOpenId(openId);
            if (ObjectUtils.isEmpty(user)) {
                user = new User();
                //取出用户相关的信息,并将相关的信息赋值给对应的属性
                user.setOpenId(openId);
                //可以需要处理一下编码问题
                user.setUserName(String.valueOf(userInfoMap.get("nickname")));
                user.setSex(Integer.valueOf(String.valueOf(userInfoMap.get("sex"))));
                user.setHeadUrl(String.valueOf(userInfoMap.get("headimgurl")));
                user.setCreatedTime(LocalDateTime.now());
                user.setUpdatedTime(LocalDateTime.now());
                userMapper.insertSelective(user);
            }
            //4、生产token，并将用户信息存入redis。返回token
            String token= UUID.randomUUID().toString().replaceAll("-","");
            String tokenKey="pet:token:"+token;
            UserInfoVO userInfoVO=new UserInfoVO();
            userInfoVO.setId(user.getId());
            userInfoVO.setUserName(user.getUserName());
            userInfoVO.setOpenId(openId);
            stringRedisTemplate.opsForValue().set(tokenKey,objectMapper.writeValueAsString(userInfoVO),30, TimeUnit.MINUTES);
            return  token;
        } catch (Exception e) {
           log.error("微信回调异常：",e);
           throw  new BaseException(StatusEnum.COMMON_EXCEPTION);
        }
    }
}
